// 12.5 友元
// 12.5.1 类模板的友元类
// 友元（friend）是C++中一种特殊的访问控制机制，允许指定的类或函数访问另一个类的私有和保护成员。在模板上下文中，友元关系变得更加复杂和强大。

// 基本友元声明
// 在类模板中，可以声明其他类或类模板为友元：
template <typename T>
class Container
{
private:
    T value;

    // 声明一个普通类为友元
    friend class Inspector;

    // 声明一个类模板为友元
    template <typename U>
    friend class Processor;
};
// 在这个例子中：
// Inspector 类可以访问任何 Container<T> 实例的私有成员
// Processor<U> 的任何实例都可以访问任何 Container<T> 实例的私有成员

// 模板参数相关的友元
// 可以声明依赖于模板参数的友元关系：
template <typename T>
class Container
{
private:
    T value;

    // T类型自身作为友元（如果T是一个类类型）
    friend T;

    // T的嵌套类作为友元
    friend typename T::NestedClass;
};
// 这种友元关系只有在T满足特定条件时才有效。

// 友元模板
// 可以将整个模板声明为友元，而不仅仅是特定实例：
template <typename T>
class Container
{
private:
    T value;

    // 声明整个Processor模板为友元
    template <typename U>
    friend class Processor;
};
// 这允许任何 Processor<U> 实例访问任何 Container<T> 实例的私有成员。

// 友元类的前向声明
// 在某些情况下，需要前向声明友元类模板：
// 前向声明
template <typename U>
class Processor;

template <typename T>
class Container
{
private:
    T value;

    // 使用前向声明的友元
    friend class Processor<T>;
};
// 这在处理相互依赖的类模板时特别有用。

// 非模板友元类
// 非模板类可以是类模板的友元，这种情况下它可以访问该模板的所有实例：
template <typename T>
class Container
{
private:
    T value;

    // 非模板友元类
    friend class GlobalInspector;
};

// GlobalInspector可以访问任何Container<T>实例
class GlobalInspector
{
public:
    template <typename T>
    void inspect(const Container<T> &c)
    {
        // 可以访问c.value
    }
};

// 友元关系的应用
// 友元关系在模板编程中有多种应用：
// 1.实现辅助类：创建能够访问模板内部的辅助类
template <typename T>
class ContainerIterator;

template <typename T>
class Container
{
private:
    T *data;
    size_t size;

    friend class ContainerIterator<T>;
};

// 2.实现运算符重载：允许非成员运算符访问私有成员
template <typename T>
class Complex
{
private:
    T real, imag;

    template <typename U>
    friend Complex<U> operator+(const Complex<U> &, const Complex<U> &);
};

// 3.实现设计模式：如观察者模式、访问者模式等
template <typename T>
class Subject;

template <typename T>
class Observer
{
private:
    friend class Subject<T>;
};